/* $RCSFile: CRMSecurity.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/Security/CRMSecurity.cs $
 * $log$
 * Revision 71 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 71 2011/02/22 01:22:13  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/01/27 09:39:42  christian.surieux
 *   Suppress lock on CRMWrapper create and start
 * Revision 6 2010/08/06 19:56:29  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Security.Principal;
using System.Web;
using System.Web.Configuration;
using System.Web.Security;
using System.Globalization;

using AddonNice.Core;
using AddonNice.Configuration;
using AddonNice.Helpers;
using AddonNice.Diagnostics;
using AddonNice.Settings;
using AddonNice.CRMWrapper;
using AddonNice.UI;


namespace AddonNice.Security
{
	public enum LogType : int { Logoff = 0, Logon = 1, Login = 2 };

	// CS 08/04 define a custom event class 
	public class LoginEventArgs : EventArgs
	{
		PortalSettings _portalSettings;
		public PortalSettings portalSettings
		{
			get
			{
				return _portalSettings;
			}
		}

		AddonNiceIdentity _usr  =   null;
		public AddonNiceIdentity User
		{
			get { return _usr; }
		}

		LogType _IsLogin = LogType.Logoff;
		public LogType IsLogin
		{
			get { return _IsLogin; }
		}
		
		bool _IsCallBack  =   false;
		public bool IsCallBack
		{
			get { return _IsCallBack; }
		}

		public LoginEventArgs(PortalSettings p, AddonNice.Security.AddonNiceIdentity usr, LogType IsLog,bool isCallBack)
		{
			_portalSettings		=   p;
			_usr				=   usr;
			_IsLogin			=   IsLog;
			_IsCallBack         =   isCallBack;
		}
	}

	public delegate void LoginEventHandler(LoginEventArgs e);


	/// <summary>
	/// The CRMPortalSecurity class encapsulates two helper methods that enable
	/// developers to easily check the role status of the current browser client.
	/// </summary>
	public class PortalSecurity 
	{
		const string strWrapper             =   "CRMWrapper";

		/// <summary>
		/// The IsUserInRoles method enables developers to easily check the role
		/// status of the current browser client against an array of roles
		/// </summary>
		public static bool IsUserInRoles(string roles) 
		{
			string CRMAdmin					=   Config.CRMAdminRole;
			if (string.IsNullOrEmpty(roles))
			{
				if (SecurityTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine("[V]PortalSecurity IsUserInroles END false roles null.", SecurityTraceSwitch.Sw.Info);
				return IsInCRMRole(CRMAdmin); // Admin goes everywhere
			}
			bool ret						=   false;
			
			string DBAllUser				=   Config.InternallAllUsersRole;
			string internalAdminRole		=   Config.InternalAdminRole;
			foreach (string splitRole in roles.Split(new char[] { ';' },StringSplitOptions.RemoveEmptyEntries)) 
			{
				string role					=   splitRole.Trim();
				if ( string.IsNullOrEmpty(role) )
					continue;
				if (role == internalAdminRole )
					role					=   CRMAdmin;
				if (role == DBAllUser || IsInCRMRole(role))
				{
					ret						=   true;
					break;
				}
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity IsUserInroles END roles: '{0}', ret: {1}", roles, ret),SecurityTraceSwitch.Sw.Info);
			return ret;
		}

		/// <summary>
		/// This object is created once for each request, it contains all the code to communicate with CRM server
		/// Wrapper is created but not initialized, it should wait a post authentication phase to be initialized (i.e. started)
		/// </summary>
		[Obsolete("Use CreateWrapper(PortalSettings ps,DBCrmServer srvObj)")]
		static public void CreateWrapper()
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]PortalSecurity CreateWrapper BEG.",SecurityTraceSwitch.Sw.Info);
			// check if !already created for this request
			lock (HttpContext.Current.Items.SyncRoot)
			{
				object ob                       =   HttpContext.Current.Items[strWrapper];
				if (ob != null && (ob is CRMWrapperBase))
				{
					const string msg            =   "[E]PortalSecurity CreateWrapper Wrapper already created";
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine(msg,SecurityTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg);
				}
				try
				{
					int CrmVersion              =   Config.CRMServiceVersion;
					string Organization         =   Config.CRMOrganization;
					int CRMAuthenticationType   =   Config.CRMAuthenticationType;
					string discoServer          =   Config.CRMDiscoServer;
					int discoserverPort         =   Config.CRMDiscoserverPort;
					string srvUrl               =   Config.CRMServer;
					string CRMServiceAccount    =   Config.CRMServiceAccount;
					string CRMServicePassword   =   Config.CRMServicePassword;
					string CRMServiceDomain     =   Config.CRMServiceDomain;
					
					string CRMPrivAccount       =   Config.CRMPrivAccount;
					string CRMPrivPassword      =   Config.CRMPrivPassword;
					string CRMPrivDomain        =   Config.CRMPrivDomain;

					string CRMDefaultAccount    =   Config.CRMDefaultAccount;
					string CRMDefaultAccountPwd =   Config.CRMDefaultAccountPassword;
					string CRMDefaultAccountDn  =   Config.CRMDefaultAccountDomain;

					string CRMAdminRoleName     =   Config.CRMAdminRole;
					
					bool UsePreAuthenticate     =   Config.CRMUsePreAuthenticate;
					
					PortalSettings ps           =   (PortalSettings)HttpContext.Current.Items[StStr.strPortalSettings];
					/*
					if ( ps != null ) 
					{
						// If we don't force CRM server with Web.Config value we initialize values from DB
						if ( !Config.ForceDefaultCRMServer )
						{
							ps.CustomSettings.IntValue(StStr.SiteSettingsCRMVersion, ref CrmVersion);
							ps.CustomSettings.IntValue(StStr.SiteSettingsCRMAuthenticationType, ref CRMAuthenticationType);
							ps.CustomSettings.StringValue(StStr.SiteSettingsCRMDiscoServer, ref discoServer);
							ps.CustomSettings.IntValue(StStr.SiteSettingsCRMDiscoServerPort, ref discoserverPort);
							ps.CustomSettings.StringValue(StStr.SiteSettingsOrganization, ref Organization);
							ps.CustomSettings.StringValue(StStr.SiteSettingsUrlServer, ref srvUrl);
							
							ps.CustomSettings.StringValue(StStr.SiteSettingsAccount, ref CRMServiceAccount);
							ps.CustomSettings.StringValue(StStr.SiteSettingsPassword, ref CRMServicePassword);
							ps.CustomSettings.StringValue(StStr.SiteSettingsDomain, ref CRMServiceDomain);
							
							ps.CustomSettings.StringValue(StStr.SiteSettingsPrivAccount, ref CRMPrivAccount);
							ps.CustomSettings.StringValue(StStr.SiteSettingsPrivPassword, ref CRMPrivPassword);
							ps.CustomSettings.StringValue(StStr.SiteSettingsPrivDomain, ref CRMPrivDomain);

							ps.CustomSettings.StringValue(StStr.SiteSettingsDefaultAccount, ref CRMDefaultAccount);
							ps.CustomSettings.StringValue(StStr.SiteSettingsDefaultPassword, ref CRMDefaultAccountPwd);
							ps.CustomSettings.StringValue(StStr.SiteSettingsDefaultDomain, ref CRMDefaultAccountDn);

							ps.CustomSettings.StringValue(StStr.SiteSettingsAdminRole, ref CRMAdminRoleName);
						}
					}
					 */
					switch (CrmVersion)
					{
						default:
						case 3:
							ob                  =   new CRMWrapper.CrmWrapper3(srvUrl, CRMServiceAccount, CRMServicePassword, CRMServiceDomain,
														CRMDefaultAccount, CRMDefaultAccountPwd, CRMDefaultAccountDn, CRMPrivAccount,CRMPrivPassword,CRMPrivDomain);
							break;
						case 4:
							ob                  =   new CRMWrapper.CrmWrapper4(Organization,discoServer,discoserverPort,
														(ADNAuthenticationType)CRMAuthenticationType,
														CRMServiceAccount, CRMServicePassword, CRMServiceDomain,
														CRMDefaultAccount, CRMDefaultAccountPwd, CRMDefaultAccountDn, 
														CRMPrivAccount,CRMPrivPassword,CRMPrivDomain,UsePreAuthenticate);
							break;
					}
					//Install Crm backup path, normally ApplicationRoot/PortalPath/CrmBackup/Default
					// install field localizer handler for DynEntity
					if ( ps != null )
					{
						( (CRMWrapperBase)ob ).CrmBackupFolder = ps.DefaultCrmBackupPath;
						if ( ps.CustomSettings[StStr.SiteSettingsCRMNUseFieldLocalizer].ToBool() )
						{
							( (CRMWrapperBase)ob ).UseFieldLocalizer = true;
							DynEntity.DynEntityEvent += new CrmDynEntityEventHandler(CRMLocalizer.DynEntity_DynEntityEvent);
							if ( SecurityTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine("[V]PortalSecurity CreateWrapper DynEntity localizer handler installed.",SecurityTraceSwitch.Sw.Info);
						}
					}
					// cache it in context
					HttpContext.Current.Items[strWrapper]   =   ob;
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine("[V]PortalSecurity CreateWrapper END Ok.",SecurityTraceSwitch.Sw.Info);
				}
				catch (Exception ex)
				{
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity CreateWrapper ex: {0}", ex),SecurityTraceSwitch.Sw.Info);
					throw;
				}
			}
		}

		/// <summary>
		/// This object is created once for each request, it contains all the code to communicate with CRM server
		/// Wrapper is created but not initialized, it should wait a post authentication phase to be initialized (i.e. started)
		/// </summary>
		static public void CreateWrapper(PortalSettings ps,DBCrmServer srvObj)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity CreateWrapper BEG CrmServerId: {0}, Organization: {1}.",srvObj.CrmServerId,srvObj.Organization),SecurityTraceSwitch.Sw.Info);
			// check if !already created for this request
			// FK4 this is locking every access to collection: lock (HttpContext.Current.Items.SyncRoot)
			{
				object ob                       =   HttpContext.Current.Items[strWrapper];
				if (ob != null && (ob is CRMWrapperBase))
				{
					const string msg            =   "[E]PortalSecurity CreateWrapper Wrapper already created.";
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine(msg,SecurityTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg);
				}
				try
				{
					switch (srvObj.CrmVersion)
					{
						default:
						case 3:
							ob                  =   new CRMWrapper.CrmWrapper3(srvObj.Server3,srvObj.ServiceAccount, srvObj.ServicePassword, srvObj.ServiceDomain,
														srvObj.DefaultAccount, srvObj.DefaultPassword, srvObj.DefaultDomain, srvObj.PrivAccount,srvObj.PrivPassword,srvObj.PrivDomain);
							break;
						case 4:
							ob                  =   new CRMWrapper.CrmWrapper4(srvObj.Organization,srvObj.DiscoServer,srvObj.DiscoServerPort,
														(ADNAuthenticationType)srvObj.AuthenticationType,
														srvObj.ServiceAccount, srvObj.ServicePassword, srvObj.ServiceDomain,
														srvObj.DefaultAccount, srvObj.DefaultPassword, srvObj.DefaultDomain, srvObj.PrivAccount,srvObj.PrivPassword,srvObj.PrivDomain,srvObj.UsePreAuthenticate);
							break;
					}
					//Install Crm backup path, normally ApplicationRoot/PortalPath/CrmBackup/Default
					// install field localizer handler for DynEntity
					if ( ps != null )
					{
						( (CRMWrapperBase)ob ).CrmBackupFolder          =   ps.DefaultCrmBackupPath;
						if ( ps.CustomSettings[StStr.SiteSettingsCRMNUseFieldLocalizer].ToBool() )
						{
							( (CRMWrapperBase)ob ).UseFieldLocalizer    =   true;
							DynEntity.DynEntityEvent                    +=  new CrmDynEntityEventHandler(CRMLocalizer.DynEntity_DynEntityEvent);
							if ( SecurityTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine("[V]PortalSecurity CreateWrapper DynEntity localizer handler installed.",SecurityTraceSwitch.Sw.Info);
						}
					}
					// cache it in context
					HttpContext.Current.Items[strWrapper]               =   ob;
					if ( SecurityTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine("[V]PortalSecurity CreateWrapper END Ok.",SecurityTraceSwitch.Sw.Info);
				}
				catch (Exception ex)
				{
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity CreateWrapper ex: {0}", ex),SecurityTraceSwitch.Sw.Info);
					throw;
				}
			}
		}

		/// <summary>
		/// Initialize (start) the Crm Wrapper, should be done only after authentication phase
		/// </summary>
		static public bool StartWrapper()
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]PortalSecurity StartWrapper BEG.",SecurityTraceSwitch.Sw.Info);
			bool init               =   false;
			// FK4 this is locking every access to collection: lock (HttpContext.Current.Items.SyncRoot)
			{
				// check if !already created for this session
				object ob               =   HttpContext.Current.Items[strWrapper];
				if (ob == null || !(ob is CRMWrapperBase))
				{
					const string msg    =   "[E]PortalSecurity StartWrapper no wrapper found in context.";
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine(msg,SecurityTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg);
				}
				CRMWrapperBase w        =   (CRMWrapperBase)ob;
				init                    =   w.isInitialized;
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity StartWrapper wrapper already initialized: {0}", init),SecurityTraceSwitch.Sw.Info);
				if ( !init )
				{
					bool UsePreAuthenticate =   Config.CRMUsePreAuthenticate;
					w.Initialize(UsePreAuthenticate);
				}
				init                    =   w.isInitialized;
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity StartWrapper END Ok, initialized: {0}", init),SecurityTraceSwitch.Sw.Info);
			return init;
		}

		
		
		/// <summary>
		/// This object is created once for each request, it contains all the code to communicate with CRM server
		/// </summary>
		static public CRMWrapperBase Wrapper
		{
			get
			{
				// check if !already created for this context
				object ob                               = HttpContext.Current.Items[strWrapper];
				if (ob == null || !(ob is CRMWrapperBase))
				{
					const string msg    =   "[E]PortalSecurity Wrapper GET no wrapper found in context";
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine(msg,SecurityTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg);
				}
				return (CRMWrapperBase)ob;
			}
		}

		/// <summary>
		/// Try to check if the role sent is amongst the roles of this user
		/// </summary>
		static bool IsInCRMRole(string role2Test)
		{
			bool ret	=	Wrapper.IsInCRMUserRoles(role2Test,Wrapper.userId);
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity IsInCRMRole END roles: '{0}', ret: {1}", role2Test, ret),SecurityTraceSwitch.Sw.Info);
			return ret;
		}

		#region Current user permissions

		/// <summary>
		/// The HasEditPermissions method enables developers to easily check 
		/// whether the current browser client has access to edit specified entity
		/// </summary>
		public static bool HasEditPermissions(string EntityName) 
		{
			return HasPermissions(EntityName,ADNCRMRights.EditAccess);
		}

		/// <summary>
		/// The HasViewPermissions method enables developers to easily check 
		/// whether the current browser client has access to view the specified entity
		/// </summary>
		public static bool HasViewPermissions(string EntityName)
		{
			return HasPermissions(EntityName, ADNCRMRights.ReadAccess);
		}

		/// <summary>
		/// The HasAddPermissions method enables developers to easily check 
		/// whether the current browser client has access to Add the specified entity
		/// </summary>
		public static bool HasAddPermissions(string EntityName)
		{
			return HasPermissions(EntityName, ADNCRMRights.AddAccess);
		}

		/// <summary>
		/// The HasAddPermissions method enables developers to easily check 
		/// whether the current browser client has access to Add the specified entity
		/// </summary>
		public static bool HasUpdatePermissions(string EntityName)
		{
			return HasPermissions(EntityName, ADNCRMRights.WriteAccess);
		}

		/// <summary>
		/// The HasDeletePermissions method enables developers to easily check 
		/// whether the current browser client has access to Delete the specified entity
		/// </summary>
		public static bool HasDeletePermissions(string EntityName)
		{
			return HasPermissions(EntityName, ADNCRMRights.DeleteAccess);
		}

		/// <summary>
		/// The HasPropertiesPermissions method enables developers to easily check 
		/// whether the current browser client has access to Properties for a module attached to specified entity
		/// </summary>
		public static bool HasPropertiesPermissions(string EntityName)
		{
			return HasPermissions(EntityName, ADNCRMRights.AdminAccess);
		}

		/// <summary>
		/// Test rights against an entity
		/// </summary>
		public static bool HasPermissions(string EntityName, ADNCRMRights r)
		{
			bool ret    =   Wrapper.HasPermissions(EntityName,r);
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity HasPermissions : {2} ,EntityName: [{0}], rights : {1}", EntityName, r, ret),SecurityTraceSwitch.Sw.Info);
			return ret;
		}
		
		/// <summary>
		/// Test for a CRM entity instance with its Guid
		/// </summary>
		public static bool HasPermissions(string EntityName, Guid EntityID, ADNCRMRights r)
		{
			throw new Exception("HasPermission not implemented");
			//return false; //TBD
			//return Wrapper.HasPermissions(EntityName, EntityID, r);
		}
		#endregion

		#region GetRoleList Methods - 

		/// <summary>
		/// Returns a string containing a list of roles corrsponding to the ParameterRol right on the module
		/// </summary>
		private static string GetPermissions(int moduleID, string procedureName, string parameterRol)
		{
			return new ModulesDB().GetPermissions(moduleID,procedureName,parameterRol);
		}

		/// <summary>
		/// The GetEditPermissions method enables developers to easily retrieve 
		/// a list of roles that have Edit Permissions 
		/// of a specified portal module.
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have Edit permissions seperated by ;</returns>
		public static string GetEditPermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthEditRoles", "@EditRoles");
		}

		/// <summary>
		/// The GetViewPermissions method enables developers to easily retrieve 
		/// a list of roles that have View permissions for the  
		/// specified portal module
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have View permissions for the specified module seperated by ;</returns>
		public static string GetViewPermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthViewRoles", "@ViewRoles");
		}

		/// <summary>
		/// The GetAddPermissions method enables developers to easily retrieve 
		/// a list of roles that have Add permissions for the 
		/// specified portal module
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have Add permissions for the specified module seperated by ;</returns>
		public static string GetAddPermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthAddRoles", "@AddRoles");
		}

		/// <summary>
		/// The GetDeletePermissions method enables developers to easily retrieve 
		/// a list of roles that have access to Delete the 
		/// specified portal module
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have delete permissions for the specified module seperated by ;</returns>
		public static string GetDeletePermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthDeleteRoles", "@DeleteRoles");
		}

		/// <summary>
		/// The GetPropertiesPermissions method enables developers to easily retrieve 
		/// a list of roles that have access to Properties for the 
		/// specified portal module
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have Properties permission for the specified module seperated by ;</returns>
		public static string GetPropertiesPermissions(int moduleID)
		{
			string roles    =   GetPermissions(moduleID, "dbo.adn_GetAuthPropertiesRoles", "@PropertiesRoles");
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity GetPropertiesPermissions END moduleID: {0}, roles: '{1}'.",moduleID,roles),SecurityTraceSwitch.Sw.Info);
			return roles;
		}

		/// <summary>
		/// The GetMoveModulePermissions method enables developers to easily retrieve 
		/// a list of roles that have access to move specified portal moduleModule. 
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have move module permission for the specified module seperated by ;</returns>
		public static string GetMoveModulePermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthMoveModuleRoles", "@MoveModuleRoles");
		}

		/// <summary>
		/// The GetDeleteModulePermissions method enables developers to easily retrieve 
		/// a list of roles that have access to delete specified portal moduleModule. 
		/// </summary>
		/// <param name="moduleID"></param>
		/// <returns>A list of roles that have delete module permission for the specified module seperated by ;</returns>
		public static string GetDeleteModulePermissions(int moduleID)
		{
			return GetPermissions(moduleID, "dbo.adn_GetAuthDeleteModuleRoles", "@DeleteModuleRoles");
		}

		#endregion


		public static event LoginEventHandler LoginEvent;

		/// <summary>
		/// Dummy class needed by InitApplication to load assembly
		/// </summary>
		public class UserInit
		{
			public UserInit() { }
		}

		private static void OnLoginEvent(PortalSettings portalSettings,AddonNiceIdentity usr,LogType IsLogin,bool isCallBk)
		{
			if ( LoginEvent != null )
				LoginEvent(new LoginEventArgs(portalSettings,usr,IsLogin,isCallBk));
		}

		/// <summary>
		/// Create an authentication cookie for 30 minutes
		/// </summary>
		public static HttpCookie SetAuthCookie(string username,string userData,bool isPersistent)
		{
			FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2,
					username,
					DateTime.Now,
					DateTime.Now.AddMinutes(30),
					isPersistent,
					userData,FormsAuthentication.FormsCookiePath
					);

			string encTicket            =   FormsAuthentication.Encrypt(ticket);
			HttpCookie cookie           =   new HttpCookie( FormsAuthentication.FormsCookieName,encTicket); 
			if (ticket.IsPersistent) 
				cookie.Expires          =   ticket.Expiration; 
			HttpContext.Current.Response.Cookies.Add(cookie);
			return cookie;
		}

		public static string UserNameFromCookie(HttpCookie cok)
		{
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity UserNameFromCookie cookie Expires: {0}, value: {1}", cok.Expires,cok.Value),SecurityTraceSwitch.Sw.Info);
			FormsAuthenticationTicket ticket    =   FormsAuthentication.Decrypt(cok.Value);
			if (SecurityTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity UserNameFromCookie cookie Name: '{0}', UserData: '{1}'", 
					ticket.Name, ticket.UserData),SecurityTraceSwitch.Sw.Info);
			return ticket.Name;
		}
		
		/// <summary>
		/// Sent by Global when a form authentication during the OnAuthenticate event wehn a cookie is detected
		/// Replaces the principal by an ADNCRMPrincipal with a new AddonNiceIDentity
		/// Beware that here the new principal is not installed
		/// </summary>
		public static void OnFormAuthenticate(FormsAuthenticationEventArgs args)
		{
			HttpCookie cok                      =   args.Context.Request.Cookies[FormsAuthentication.FormsCookieName];
			if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity OnFormAuthenticate BEG cookie: {0}, null: {1}", FormsAuthentication.FormsCookieName,(cok==null)),
					(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			if ( cok != null )
			{
				if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
					Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity OnFormAuthenticate cookie Expires: {0}, value: {1}",cok.Expires,cok.Value),
						( SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info : AuthenticationTrace.Sw.Info);
				FormsAuthenticationTicket ticket    =   FormsAuthentication.Decrypt(cok.Value);
				if ( SecurityTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity OnFormAuthenticate creating ADNCRMPrincipal with cookie Name: '{0}', UserData: '{1}'",
						ticket.Name,ticket.UserData),SecurityTraceSwitch.Sw.Info);
				string userData                     =   ticket.UserData;
				AddonNiceIdentity Aid               =   new AddonNiceIdentity(ticket.Name,userData);
				args.User                           =   new ADNCRMPrincipal(args.User,Aid,new string[0]);
				SignOn(Aid);
				// Extend Cookie, or we could get problems with some axd with an expired cookie
				DateTime time                       =   DateTime.Now;
				int minuteAdd	                    =	Config.CookieExpire;
				TimeSpan span                       =   new TimeSpan(0,0,minuteAdd,0,0);
				cok.Expires                         =   time.Add(span);
			}
		}

		/// <summary>
		/// Single point for logging on an user after Form Authentication.
		/// </summary>
		public static void SignOn(AddonNiceIdentity usr)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity SignOn BEG Name: {0}.", usr.Name),
					(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			// Obtain PortalSettings from Current Context
			PortalSettings portalSettings   =   (PortalSettings) HttpContext.Current.Items[StStr.strPortalSettings];
			
			// Get user's window configuration
			if (Config.WindowMgmtControls)
			{
				// first clear any state the user may have in the bag (cookie,session,application)
				AddonNice.BLL.UserConfig.UserDesktop.ResetDesktop(usr.CrmId);
				AddonNice.BLL.UserConfig.UserDesktop.ConfigureDesktop(usr.CrmId, portalSettings.PortalID);
			}
			// triggers a login event
			try
			{
				OnLoginEvent(portalSettings ,usr,LogType.Logon,false);
			}
			catch(Exception ex)
			{
				if (SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity SignOn OnLoginEvent portalID: {0}, ex : {1}",
						portalSettings.PortalID, ex),SecurityTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// Real Login via UI
		/// </summary>
		public static void Login(AddonNiceIdentity usr)
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity Login BEG Name: {0}.", usr.Name),
					(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			// Obtain PortalSettings from Current Context
			PortalSettings portalSettings   =   (PortalSettings) HttpContext.Current.Items[StStr.strPortalSettings];
			
			// triggers a login event
			try
			{
				OnLoginEvent(portalSettings ,usr,LogType.Login,false);
			}
			catch(Exception ex)
			{
				if (SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity Login OnLoginEvent portalID: {0}, ex : {1}",
						portalSettings.PortalID, ex),SecurityTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// Single point logoff
		/// </summary>
		public static void SignOut()
		{
			PortalSecurity.SignOut(HttpUrlBuilder.BuildUrl(), Config.UseAlias);
		}

		/// <summary>
		/// Single point logoff
		/// RemoveLogin no more used but kept in case...
		/// </summary>
		public static void SignOut(string urlToRedirect, bool removeLogin)
		{
			AuthenticationMode md   =   Config.AuthenticationMode;
			if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity SignOut BEG urlToRedirect: {0}, removeLogin: {1}, Config.AuthenticationMode: {2}",
					urlToRedirect,removeLogin,md),
					(SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			// Log User Off from Cookie Authentication System
			if ( md != AuthenticationMode.Forms )
				return;
			FormsAuthentication.SignOut();
	  
			/*
			// Invalidate roles token
			HttpCookie hck	= HttpContext.Current.Response.Cookies[CPortalRoles];
			hck.Value		= null;
			hck.Expires		= new System.DateTime(1999, 10, 12);
			hck.Path		= "/";
			*/

			// Obtain PortalSettings from Current Context
			PortalSettings portalSettings = (PortalSettings) HttpContext.Current.Items[StStr.strPortalSettings];

			// remove user window information
			// User Information
			// valid user
			if ( (HttpContext.Current.User != null) && (HttpContext.Current.User is ADNCRMPrincipal) )
			{
				ADNCRMPrincipal p	    =	(ADNCRMPrincipal)HttpContext.Current.User;
				AddonNiceIdentity user  =   p.AddonNiceIdentity;
				try 
				{
					if (Config.WindowMgmtControls)
						AddonNice.BLL.UserConfig.UserDesktop.ResetDesktop(user.CrmId);
					if(Config.IsMonitoringEnabled)
					{
						OnLoginEvent(portalSettings ,user,LogType.Logoff,false);
					}
				} 
				catch(Exception ex)
				{
					if ( SecurityTraceSwitch.Sw.TraceError )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity SignOut ex : {0}", ex),SecurityTraceSwitch.Sw.Info);
				}
			}
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity SignOut url: {0}", urlToRedirect),SecurityTraceSwitch.Sw.Info);

			//Redirect user back to the Portal Home Page
			if ( urlToRedirect != string.Empty ) 
				HttpContext.Current.Response.Redirect(urlToRedirect);
		}
		
		/// <summary>
		/// Kills session after timeout
		/// </summary>
		public static void KillSession()
		{
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine("[V]PortalSecurity KillSession BEG.",SecurityTraceSwitch.Sw.Info);
			// as there is no login in this version, we go to home page
			PortalSecurity.SignOut(HttpUrlBuilder.BuildUrl(), true);
		}

		/// <summary>
		/// Redirect user back to the Portal Home Page.
		/// </summary>
		public static void PortalHome(bool NoHistory,ADNPage Pg)
		{
			string url  =   HttpUrlBuilder.BuildUrl();
			if ( SecurityTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalSecurity PortalHome Pg: '{0}', noHistory: {1}, url: '{2}'.",( Pg != null ) ? Pg.Title:string.Empty,NoHistory,url),SecurityTraceSwitch.Sw.Info);
			if ( NoHistory )
				Pg.Response.Cache.SetCacheability(HttpCacheability.NoCache);
			if ( Pg != null )
				Pg.Redirect(url,true);
			else HttpContext.Current.Response.Redirect(url);
		}

		/// <summary>
		/// Single point access deny.
		/// Called when there is an unauthorized access attempt.
		/// </summary>
		public static void AccessDenied()
		{
			if ( SecurityTraceSwitch.Sw.TraceError )
				Trace.WriteLine("[V]PortalSecurity AccessDenied.",SecurityTraceSwitch.Sw.Info);
			//if ( !HttpContext.Current.User.Identity.IsAuthenticated )
				throw new HttpException(403, "Access Denied", 2);
		}

		/// <summary>
		/// Single point edit access deny.
		/// Called when there is an unauthorized access attempt to an edit page.
		/// </summary>
		public static void AccessDeniedEdit()
		{
			if ( SecurityTraceSwitch.Sw.TraceError )
				Trace.WriteLine("[V]PortalSecurity AccessDeniedEdit.",SecurityTraceSwitch.Sw.Info);
			throw new HttpException(403, "Access Denied Edit", 3);
		}

		/// <summary>
		/// Single point edit access deny from the Secure server (SSL)
		/// Called when there is an unauthorized access attempt to an edit page.
		/// </summary>
		public static void SecureAccessDenied()
		{
			if ( SecurityTraceSwitch.Sw.TraceError )
				Trace.WriteLine("[V]PortalSecurity SecureAccessDenied.",SecurityTraceSwitch.Sw.Info);
			throw new HttpException(403, "Secure Access Denied", 3);
		}

		/// <summary>
		/// Single point get all CRM roles 
		/// </summary>
		public static string[] GetCRMRoles()
		{
			try
			{
				return Wrapper.GetStrAllRoles();
			}
			catch (Exception ex)
			{
				//no roles
				if ( SecurityTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalSecurity GetCRMRoles ex :{0}", ex),SecurityTraceSwitch.Sw.Info);
				throw;
			}

		}
	}
}